package com.riguz.forks.framework.db.dbutils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import com.riguz.forks.framework.db.Column;
import com.riguz.gags.base.Strings;

public class MappedBeanProcessor<T> extends org.apache.commons.dbutils.BeanProcessor {
    private final Map<String, String> fieldOverrides = new HashMap<>();

    public MappedBeanProcessor(Class<T> beanClass) {
        getOverrides(beanClass);
    }

    protected void getOverrides(Class<T> beanClass) {
        for (Field field : beanClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Column.class)) {
                fieldOverrides.put(field.getAnnotation(Column.class).value(), field.getName());
            }
        }
    }

    @Override
    protected int[] mapColumnsToProperties(ResultSetMetaData rsmd, PropertyDescriptor[] props) throws SQLException {
        // props: The 0th element is meaningless because JDBC column indexing starts at 1.
        final int cols = rsmd.getColumnCount();
        final int[] columnToProperty = new int[cols + 1];
        Arrays.fill(columnToProperty, PROPERTY_NOT_FOUND);

        for (int col = 1; col <= cols; col++) {
            String columnName = rsmd.getColumnLabel(col);

            if (Strings.isNullOrEmpty(columnName)) columnName = rsmd.getColumnName(col);

            String overrideName = fieldOverrides.get(columnName);
            if (overrideName == null) overrideName = columnName;

            final String generousColumnName = columnName.replace("_", "");

            for (int i = 0; i < props.length; i++) {
                final String propName = props[i].getName();

                // see if either the column name, or the generous one matches
                if (columnName.equalsIgnoreCase(propName) || generousColumnName.equalsIgnoreCase(propName) || overrideName.equalsIgnoreCase(propName)) {
                    columnToProperty[col] = i;
                    break;
                }
            }
        }

        return columnToProperty;
    }
}
